﻿using Deployment.Data.Environment.Connection;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Xml.Serialization;

namespace Deployment.Data.SQL.Connections
{
    public abstract class AbstractSQLConnection : AbstractConnection
    {
        protected internal SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

        public AbstractSQLConnection() : base()
        {
            IntegratedSecurity = true;
        }

        [XmlIgnore]
        public string SQLServer
        {
            get { return builder.DataSource; }
            set
            {
                if (value == null)
                    value = String.Empty;
                if (!string.Equals(builder.DataSource, value, StringComparison.CurrentCulture))
                {
                    IsInternalDataUpdate = true;
                    builder.DataSource = value;
                    Data = builder.ConnectionString;
                    OnPropertyChanged("SQLServer");
                }
            }
        }

        [XmlIgnore]
        public bool IntegratedSecurity
        {
            get { return builder.IntegratedSecurity; }
            set
            {
                if (builder.IntegratedSecurity != value)
                {
                    builder.IntegratedSecurity = value;
                    IsInternalDataUpdate = true;
                    Data = builder.ConnectionString;
                    OnPropertyChanged("IntegratedSecurity");
                }
            }
        }

        [XmlIgnore]
        public string User
        {
            get { return builder.UserID; }
            set
            {
                if (!string.Equals(builder.UserID, value, StringComparison.CurrentCulture))
                {
                    IsInternalDataUpdate = true;
                    builder.UserID = value;
                    Data = builder.ConnectionString;
                    OnPropertyChanged("User");
                }
            }
        }

        [XmlIgnore]
        public string Password
        {
            get { return builder.Password; }
            set
            {
                if (!string.Equals(builder.Password, value, StringComparison.CurrentCulture))
                {
                    IsInternalDataUpdate = true;
                    builder.Password = value;
                    Data = builder.ConnectionString;
                    OnPropertyChanged("Password");
                }
            }
        }

        [XmlIgnore]
        public string ApplicationName
        {
            get { return builder.ApplicationName; }
            set
            {
                if (builder.ApplicationName != value)
                {
                    builder.ApplicationName = value;
                    IsInternalDataUpdate = true;
                    Data = builder.ConnectionString;
                    OnPropertyChanged("ApplicationName");
                }
            }
        }

        protected override void onDataUpdated()
        {
            if (Data != builder.ConnectionString)
            {
                builder.ConnectionString = Data;
                //fire all property change events.
                OnPropertyChanged("SQLServer");
                OnPropertyChanged("IntegratedSecurity");
                OnPropertyChanged("User");
                OnPropertyChanged("Password");
                OnPropertyChanged("ApplicationName");
                subClassOnDataUpdated();
            }
            //builder.ConnectionString = this.Data;
            //builder.ApplicationName;
            //builder.AsynchronousProcessing;
            //builder.AttachDBFilename;
            //builder.ConnectTimeout;
            //builder.ContextConnection;
            //builder.DataSource;
            //builder.Encrypt;
            //builder.FailoverPartner;
            //builder.InitialCatalog;
            //builder.IntegratedSecurity;
            //builder.LoadBalanceTimeout;
            //builder.MaxPoolSize;
            //builder.MinPoolSize;
            //builder.MultipleActiveResultSets;
            //builder.NetworkLibrary;
            //builder.PacketSize;
            //builder.Password;
            //builder.PersistSecurityInfo;
            //builder.Pooling;
            //builder.Replication;
            //builder.TrustServerCertificate;
            //builder.UserID;
            //builder.UserInstance;
            //builder.WorkstationID;

        }

        protected abstract void subClassOnDataUpdated();

        protected override bool PerformConnectionValidation(out string message)
        {
            using (SqlConnection con = new SqlConnection(builder.ConnectionString))
            {
                try
                {
                    return performConnectionAccessChecks(con, out message);
                }
                catch (InvalidOperationException e)
                {
                    Debug.WriteLine(e);
                    message = e.Message;
                    return false;
                }
                catch (SqlException e)
                {
                    Debug.WriteLine(e);
                    message = e.Message;
                    return false;
                }
            }
        }

        protected abstract bool performConnectionAccessChecks(SqlConnection connection, out string message);

        protected abstract bool DataValid();

        protected override bool connectionDataValid()
        {
            return (!string.IsNullOrEmpty(SQLServer) &&
                (!this.IntegratedSecurity && (!string.IsNullOrEmpty(User) && !string.IsNullOrEmpty(Password)) ||
                this.IntegratedSecurity) && DataValid());
        }
    }
}
